import uuid
from dataclasses import dataclass
from typing import Any

import pytest
from sqlalchemy import insert
from sqlalchemy.ext.asyncio import AsyncSession

from recruit.adapter.database.gateway import ResumeWorkGateway
from recruit.adapter.database.models import Resume, ResumeWork
from .fixtures.resume import ResumeTest
from .utils import delete_user, check_attr_model, check_get_one, get_resume


@dataclass
class ResumeWorkTest:
    id: uuid.uuid4()
    resume_id: uuid.uuid4()
    start_work: int
    end_work: int
    position: str
    company: str
    workplace: str


async def _create_resume_work(
        session: AsyncSession,
        data: dict[str, Any]
) -> ResumeWorkTest:
    stmt = insert(ResumeWork).values(**data).returning(ResumeWork)
    resume_work = (await session.execute(stmt)).scalar_one()
    resume_work = ResumeWorkTest(
        id=resume_work.id,
        resume_id=resume_work.resume_id,
        start_work=resume_work.start_work,
        end_work=resume_work.end_work,
        position=resume_work.position,
        company=resume_work.company,
        workplace=resume_work.workplace
    )
    await session.commit()
    return resume_work


async def test_create(
        db_session: AsyncSession,
        get_resume_work: dict[str, Any],
        create_resume: ResumeTest
) -> None:
    resume_work_gateway = ResumeWorkGateway(db_session)
    get_resume_work['resume_id'] = create_resume.id
    resume_work = await resume_work_gateway.create(**get_resume_work)
    assert isinstance(resume_work.resume, Resume)
    check_attr_model(resume_work, get_resume_work)
    await db_session.commit()
    await delete_user(db_session, create_resume.user_id)


@pytest.mark.parametrize(
    'keys', [
        ('id', 'resume_id', 'start_work', 'end_work', 'position', 'company',
         'workplace')
    ]
)
async def test_get_one(
        keys: tuple[str, ...],
        db_session: AsyncSession,
        get_resume_work: dict[str, Any],
        create_resume: ResumeTest
) -> None:
    resume_work_gateway = ResumeWorkGateway(db_session)
    get_resume_work['resume_id'] = create_resume.id
    created_resume_work = await _create_resume_work(
        db_session,
        get_resume_work
    )
    for key, value in get_resume_work.items():
        resume_work = await resume_work_gateway.get_one(**{key: value})
        assert resume_work is not None
        check_get_one(resume_work, created_resume_work, keys)
    await delete_user(db_session, create_resume.user_id)


async def test_check_resume(
        db_session: AsyncSession,
        get_resume_work: dict[str, Any],
        create_resume: ResumeTest
) -> None:
    resume_work_gateway = ResumeWorkGateway(db_session)
    get_resume_work['resume_id'] = create_resume.id
    created_resume_work = await _create_resume_work(
        db_session,
        get_resume_work
    )
    val = await resume_work_gateway.check_resume(
        created_resume_work.resume_id
    )
    assert val
    await delete_user(db_session, create_resume.user_id)
    val = await resume_work_gateway.check_resume(
        created_resume_work.resume_id
    )
    assert not val


async def test_delete(
        db_session: AsyncSession,
        get_resume_work: dict[str, Any],
        create_resume: ResumeTest
) -> None:
    resume_work_gateway = ResumeWorkGateway(db_session)
    get_resume_work['resume_id'] = create_resume.id
    created_resume_work = await _create_resume_work(
        db_session,
        get_resume_work
    )
    await resume_work_gateway.delete(created_resume_work.resume_id)
    await db_session.commit()
    await delete_user(db_session, create_resume.user_id)
    resume_work = await get_resume(
        db_session,
        ResumeWork,
        created_resume_work.resume_id
    )
    assert resume_work is None
